// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// Author: wsfuyibing <682805@qq.com>
// Date: 2024-12-05

package src

import (
	"context"
	"gitee.com/go-libs/log"
	"gitee.com/go-libs/process"
	"gitee.com/gomq/sr"
	"sync"
)

// This is a component for rabbitmq operations, It's implemented on
// sr.Servlet.
type manager struct {
	mu      *sync.RWMutex
	name    string
	process process.Process

	client   *client
	config   *config
	producer sr.Producer
	remoting sr.Remoting
}

// New creates a new sr.Servlet instance used to operate rabbitmq services.
func New() sr.Servlet {
	return (&manager{}).init()
}

// Configure configures sr.Servlet with json data.
func (o *manager) Configure(data []byte) (err error) {
	return o.config.unmarshal(data)
}

// Consumer creates a new sr.Consumer instance to receive messages from
// queue. It's schedule received messages to given executor.
func (o *manager) Consumer(name string, subscription sr.Subscription, executor sr.Executor) sr.Consumer {
	return (&consumer{
		executor:     executor,
		manager:      o,
		name:         name,
		subscription: subscription,
	}).init()
}

// Process returns a process.Process instance, It works like a process of
// linux os.
func (o *manager) Process() process.Process {
	return o.process
}

// Producer returns a singleton instance of sr.Producer. It's publish
// messages to given topic of rabbitmq.
func (o *manager) Producer() sr.Producer {
	return o.producer
}

// Remoting returns a singleton instance of sr.Remoting. It's initialize
// or destroy server settings of rabbitmq.
func (o *manager) Remoting() sr.Remoting {
	return o.remoting
}

// + Process: implemented on process.Process

func (o *manager) After(_ context.Context) (err error) {
	log.Debugf("[servlet=rabbitmq] stopped")
	return
}

func (o *manager) Before(_ context.Context) (err error) {
	log.Debugf("[servlet=rabbitmq] startup")
	return
}

func (o *manager) Run(ctx context.Context) (err error) {
	for {
		select {
		case <-ctx.Done():
			return
		}
	}
}

// + Access

func (o *manager) init() *manager {
	o.mu = new(sync.RWMutex)
	o.name = "rabbitmq-servlet"
	log.Infof("[servlet=rabbitmq] initializing")

	o.config = &config{}
	o.client = (&client{manager: o}).init()
	o.producer = (&producer{manager: o}).init()
	o.remoting = (&remoting{manager: o}).init()

	o.process = process.New(o.name, o)
	o.process.Add(o.producer.Process().Prevent(true))
	o.process.Add(o.remoting.Process().Prevent(true))
	return o
}
